/**
 * uart4Host.c - The C source file of the uart Driver for host
 * NOTE: This file is based on HAL library of stm32 platform
 *       
 * Copyright (c) 2020-, garbage classify Project
 *
 * SPDX-License-Identifier: Apache-2.0
 *
 * Change Logs:
 * Date           Author            Notes           mail
 * 2021-03-04     江榕煜       first version   2373180028@qq.com
**/

#include "uart4Host.h"
#include "stdio.h"
#include "IMU_WT931.h"
#include "BSP.h"
#include "system.h"

#define _HOST_DEBUG_PRINT_

/***********通信收发缓存定义**********/

struct rt_semaphore recv_sem;    // 成功接收一帧数据信号量
uint8_t RecvCache4Host[HOST_BUFFER_LENGTH];

/*************函数定义*************/

/** @brief  上位机通信初始化接口
 *  @note   
 *          使用上位机的功能前必须调用该接口
 *  @author 江榕煜（2021.2.1）
 *  @param 
 *          None
 *  @retval 
 *          rt_sem_t    成功接收信号量控制器
**/
rt_sem_t uart4HostInit()
{
    // 初始化接收信号量
    rt_sem_init(&recv_sem, "host Recv", 0, RT_IPC_FLAG_FIFO);
    
    // 启动DMA串口数据接收
    //HAL_UART_Receive_DMA(&HostUartHandler,(uint8_t *) recvCachePtr, sizeof(hostCommand));
    
    // 串口DMA接收使能
    __HAL_UART_CLEAR_FLAG(&HostUartHandler, UART_FLAG_PE); //清空各标志位
    __HAL_UART_CLEAR_FLAG(&HostUartHandler, UART_FLAG_FE);
    __HAL_UART_CLEAR_FLAG(&HostUartHandler, UART_FLAG_NE);
    __HAL_UART_CLEAR_FLAG(&HostUartHandler, UART_FLAG_ORE);
    HostUartHandler.Instance->RDR;  // 清空原有接收寄存器
    HAL_UART_Receive_DMA(&HostUartHandler,RecvCache4Host,HOST_BUFFER_LENGTH);    // 开始DMA

    
    // 返回接收控制量句柄
    return &recv_sem;
}

/** @brief  发送数据给上位机
 *  @note   
 *  @author 江榕煜（2021.3.12）
 *  @param  
 *      sendPtr(localMsg *) 发送的帧指针
 *  @retval None
**/
void uart4Host_send(localMsg* sendPtr)
{
    HAL_UART_Transmit_DMA(&HostUartHandler,(uint8_t *)sendPtr,sizeof(localMsg));
}

/** @brief  串口接收完毕回调函数
 *  @note   
 *          启动串口中断接收或者DMA接收
 *  @author 江榕煜（2021.2.1）
 *  @param 
 *          huart   uart句柄
 *  @retval None
**/


#ifdef DATA_FEEDBACK

/** @brief  数据反馈
 *  @note   用于电脑端查看数据波形
 *  @author 江榕煜（2021.6.11）
 *  @param  None
 *  @retval None
**/
void uart4Host_feedback(void)
{
    /* ---外部数据引入。WARN：这个法子耦合度太高，后面有空改掉--- */
    extern int32_t wheelSpeed_Left,wheelSpeed_Right;
    extern double motorDuty_Left,motorDuty_Right;
    extern WT931_9AxisData * IMU;
    extern PID PID_vel,PID_ang;
    static char feedbackString[200];
    sprintf(feedbackString,
            "%d,%d,%d,%lf,%lf,%lf\n", // 输出左、右轮转速、平衡倾角、角度环输出、速度环输出、速度环积分
            wheelSpeed_Left,
            wheelSpeed_Right,
            IMU->Angle.Angle[0],
            PID_ang.output,
            PID_vel.output,
            PID_vel.SumI);
    HAL_UART_Transmit_DMA(&HostUartHandler,(uint8_t *)feedbackString,strlen(feedbackString));
}

#endif

/** @brief  上位机接收回调函数
 *  @note   收到一个完整帧，目前没有做自动字节序对齐
 *  @author 江榕煜（2021.6.15）
 *  @param  huart(UART_HandleTypeDef *) 串口对象
 *  @retval None
**/
void HostRecv_RxCpltCallback(UART_HandleTypeDef *huart)
{
    /* ---外部数据引入。WARN：这个法子耦合度太高，后面有空改掉--- */
    extern struct rt_semaphore sem_YuntaiServer;    // 云台服务
    extern float pitch_Pos,yaw_Pos; // yunTai.c
    extern rt_mailbox_t attackCmd_mailBoxHandler;  // 在sysInit.c
    
    /* --- 安全校验 --- */
    if(huart != &HostUartHandler)   return; 
    
    /* --- 数据解析 --- */
    int speed, angle;
    if(RecvCache4Host[0] == 0xa9 && RecvCache4Host[4] ==0xa6)
    {
        // 包头包尾检验成功
        // 开始做包信息解析
        switch(RecvCache4Host[1])
        {
            // 小车控制
            case(0x0):
            {
                speed = *((uint8_t *)(RecvCache4Host+2));
                speed -= 100;   // -100~+100
                extern double vel_DeltaI;
                vel_DeltaI = -0.001 * speed;   // 小车速度最大0.1
                
                angle = *((uint8_t*)(RecvCache4Host+3));
                angle -= 90;    // -90~+90
                extern PID PID_rotate;
                PID_rotate.target = angle * 2;
                
                break;
            }
            //电磁炮
            case(0x1):
            {
                switch(RecvCache4Host[2])//参数1
                {
                case(1):
                {
                    //检查状态
                    break;
                }
                case(2):
                {
                    //准备发射，充电
                    rt_mb_send(attackCmd_mailBoxHandler,1);
                    break;
                }
                case(3):
                {
                    //发射
                    rt_mb_send(attackCmd_mailBoxHandler,2);
                    break;
                }
                case(4):
                {
                    //毁灭模式
                    break;
                }
                default:
                    break;
                }
                break;
            }
            //云台
            case(0x2):
            {
                angle = *((int8_t*)(RecvCache4Host+3)) - 90;
                switch(RecvCache4Host[2])//参数1
                {
                case(0):
                {
                    //云台启动
                    break;
                }
                case(1):
                {
                    //左右倾
                    pitch_Pos -= angle;
                    
                    if(pitch_Pos > 100) pitch_Pos = 100;
                    else if(pitch_Pos < -100) pitch_Pos = -100;
                    
                    rt_sem_release(&sem_YuntaiServer);
                    break;
                }
                case(2):
                {
                    //上下倾
                    yaw_Pos += angle;
                    
                    if(yaw_Pos > 100) yaw_Pos = 100;
                    else if(yaw_Pos < -100) yaw_Pos = -100;
                    
                    rt_sem_release(&sem_YuntaiServer);
                    break;
                }
                case(3):
                {
                    // 设置激光亮度
                    laserCtrl(RecvCache4Host[3]);
                    break;
                }
                default:
                    break;
                }

                break;
            }
            
            // 开关机指令
            case(0x3):
            {
                switch(RecvCache4Host[2])//参数1
                {
                    case(0):
                    {
                        //开机
                        ENABLE_BALANCE_CTRL();
                        break;
                    }
                    case(1):
                    {
                        //关机
                        DISABLE_BALANCE_CTRL();
                        break;
                    }
                    default:
                        break;
                }
                break;
            }
            default:
                break;
        }
    }
    
    // 继续DMA接收
    HAL_UART_Receive_DMA(&HostUartHandler,RecvCache4Host,HOST_BUFFER_LENGTH);
}

